package com.hushan.elevator.service.impl;

import com.hushan.elevator.dao.DeviceInfoRepository;
import com.hushan.elevator.dao.DeviceTypeRepository;
import com.hushan.elevator.dao.UserRepository;
import com.hushan.elevator.model.*;
import com.hushan.elevator.security.SecurityUtils;
import com.hushan.elevator.service.DeptService;
import com.hushan.elevator.service.DeviceInfoService;
import com.hushan.elevator.utils.Result;
import com.hushan.elevator.utils.ResultCode;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: zzy
 * @Date: 2024/10/22 22:53
 * @Title:
 * @Version:
 * @Package: com.hushan.elevator.service.impl
 */
@Service
public class DeviceInfoServiceImpl implements DeviceInfoService {

    private final DeviceInfoRepository deviceInfoDao;
    private final DeptService deptService;
    private final DeviceTypeRepository deviceTypeDao;
    private final UserRepository userDao;

    @Autowired
    public DeviceInfoServiceImpl(DeviceInfoRepository deviceInfoRepository, DeptService deptService, DeviceTypeRepository deviceTypeDao, UserRepository userDao) {
        this.deviceInfoDao = deviceInfoRepository;
        this.deptService = deptService;
        this.deviceTypeDao = deviceTypeDao;
        this.userDao = userDao;
    }

    @Override
    public boolean detectAuthorize(Integer id) {
        User requestUser = SecurityUtils.getUser();

        DeviceInfo info = findById(id);
        Department deviceInfoDept = deptService.findDeptById(info.getDeptId());

        return deptService.findUserPermissionForDept(requestUser, deviceInfoDept);
    }

    @Override
    public boolean detectAuthorize(int userId, Integer id) {
        User requestUser = userDao.findByUserId(userId).orElse(null);
        DeviceInfo info = findById(id);
        Department deviceInfoDept = deptService.findDeptById(info.getDeptId());
        return deptService.findUserPermissionForDept(requestUser, deviceInfoDept);
    }

    @Override
    public boolean detectAuthorize(User user, Integer id) {
        DeviceInfo info = findById(id);
        Department deviceInfoDept = deptService.findDeptById(info.getDeptId());
        return deptService.findUserPermissionForDept(user, deviceInfoDept);
    }


    @Override
    @Transactional
    public void add(DeviceInfo deviceInfo) {
        deviceInfo.setLatestTime(LocalDateTime.now());
        deviceInfo.setInterfaceType("暂未设置");
        deviceInfo.setSoftwareType("暂未设置");
        deviceInfo.setStatus(1);
        deviceInfo.onCreate();
        deviceInfoDao.save(deviceInfo);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        deviceInfoDao.deleteById(id);
    }

    @Override
    public void update(DeviceInfo deviceInfo) {
        deviceInfoDao.save(deviceInfo);
    }

    @Override
    public DeviceInfo findById(Integer id) {
        return deviceInfoDao.findById(id).orElse(null);
    }

    @Override
    public int findCountByDept(int id) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setDeptId(id);
        deviceInfo.setIsDeleted(false);
        return findCount(deviceInfo);
    }

    @Override
    public int findOnlineCountByDept(boolean online, int id) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setDeptId(id);
        deviceInfo.setStatus(online ? 1 : 0);
        deviceInfo.setIsDeleted(false);
        return findCount(deviceInfo);
    }

    @Override
    public List<DeviceInfo> findByDeptId(int id) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setDeptId(id);
        deviceInfo.setIsDeleted(false);
        Example<DeviceInfo> deviceInfoExample = Example.of(deviceInfo);
        return deviceInfoDao.findAll(deviceInfoExample);
    }

    @Override
    public List<DeviceInfo> findOnlineByDeptId(int id) {
        DeviceInfo deviceInfo = new DeviceInfo();
        deviceInfo.setDeptId(id);
        deviceInfo.setStatus(1);
        deviceInfo.setIsDeleted(false);
        Example<DeviceInfo> deviceInfoExample = Example.of(deviceInfo);
        return deviceInfoDao.findAll(deviceInfoExample);
    }

    @Override
    public DeviceInfo findBySerialNumb(String deviceSerial) {
        return deviceInfoDao.findBySerialNumber(deviceSerial);
    }

    @Override
    public DeviceType findTypeById(int deviceId) {
        DeviceInfo info = findById(deviceId);
        return deviceTypeDao.findById(info.getDeviceType()).orElse(null);
    }

    @Override
    public DeviceType findType(DeviceInfo info) {
        return deviceTypeDao.findById(info.getDeviceType()).orElse(null);
    }

    @Override
    public int[] findCountInDept(Integer deptId) {
        List<Department> childDept = deptService.findChildByDeptId(deptId);
        int[] rst = new int[3];
        int deptCount = findCountByDept(deptId);
        int online = findOnlineCountByDept(true, deptId);
        int offline = deptCount - online;
        for (Department item : childDept) {
            deptCount += findCountByDept(item.getDeptId());
            offline += findOnlineCountByDept(false, item.getDeptId());
            online += findOnlineCountByDept(true, item.getDeptId());
        }
        rst[0] = deptCount;
        rst[1] = online;
        rst[2] = offline;
        return rst;
    }

    @Override
    public List<DeviceType> findTypes() {
        return deviceTypeDao.findAll();
    }

    @Override
    public List<DeviceInfo> findAll() {
        return deviceInfoDao.findAll();
    }

    @Override
    public void online(String devid, boolean b) {
        deviceInfoDao.updateOnlineBySerialNumber(b?1:0,devid);
    }


    @Override
    public List<DeviceInfo> findChildDeptDeviceByDeptId(int id) {
        List<Department> childByDeptId = deptService.findChildByDeptId(id);
        childByDeptId.add(deptService.findDeptById(id));
        List<DeviceInfo> rst = new ArrayList<>();
        for (Department childDept : childByDeptId) {
            // has or not device in this dept
            long count = findCountByDept(childDept.getDeptId());
            if (count > 0) {
                rst.addAll(deviceInfoDao.findByDeptId(childDept.getDeptId()));
            }
        }
        return rst;
    }

    @Override
    public List<DeviceInfo> findChildDeptDeviceByDeptId(Integer deptId, PageRequest pageRequest) {
        List<Department> childByDeptId = deptService.findChildByDeptId(deptId);
        childByDeptId.add(deptService.findDeptById(deptId));
        List<DeviceInfo> rst = new ArrayList<>();
        for (Department childDept : childByDeptId) {
            // has or not device in this dept
            long count = findCountByDept(childDept.getDeptId());
            if (count > 0) {
                rst.addAll(deviceInfoDao.findByDeptId(childDept.getDeptId()));
            }
        }
        return rst;
    }

    public int findCount(DeviceInfo deviceInfo) {
        Example<DeviceInfo> deviceInfoExample = Example.of(deviceInfo);
        return (int) deviceInfoDao.count(deviceInfoExample);
    }
}